﻿using System;
using Microsoft.VisualStudio.TestPlatform.UnitTestFramework;
using QKit;
using System.Collections.Generic;
using System.Threading.Tasks;
using Windows.UI.Xaml;
using Windows.ApplicationModel.Core;
using Windows.UI.Core;
using System.Collections.ObjectModel;

namespace QKitUnitTestApp
{
    [TestClass]
    public class LinearDialTest
    {
        List<double> markerValueList = new List<double> { 0, 10, 20, 30, 0 };

        [TestMethod]
        public async Task CreateDialMarkerValues_moreThanThree()
        {
            List<double> result = null;
            ObservableCollection<double> displayResult = null;
            await TestUtil.GetDispatcher().RunAsync(CoreDispatcherPriority.Normal, () =>
            {
                var dial = new LinearDial
                {
                    Minimum = 30,
                    Maximum = 70,
                    MarkerInterval = 10
                };
                dial.CreateDialMarkerValues();
                result = dial.actualDialMarkerValues;
                displayResult = dial.displayDialMarkerValues;
            });

            Assert.IsNotNull(result);
            Assert.IsNotNull(displayResult);
            Assert.AreEqual(result.Count, 5);
            Assert.AreEqual(displayResult.Count, 5);
            Assert.AreEqual(30, result[0]);
            Assert.AreEqual(40, result[1]);
            Assert.AreEqual(50, result[2]);
            Assert.AreEqual(60, result[3]);
            Assert.AreEqual(70, result[4]);
            Assert.AreEqual(30, displayResult[0]);
            Assert.AreEqual(40, displayResult[1]);
            Assert.AreEqual(50, displayResult[2]);
            Assert.AreEqual(60, displayResult[3]);
            Assert.AreEqual(70, displayResult[4]);
        }

        [TestMethod]
        public async Task CreateDialMarkerValues_exactlyThree()
        {
            List<double> result = null;
            ObservableCollection<double> displayResult = null;
            await TestUtil.GetDispatcher().RunAsync(CoreDispatcherPriority.Normal, () =>
            {
                var dial = new LinearDial
                {
                    Minimum = 30,
                    Maximum = 70,
                    MarkerInterval = 20
                };
                dial.CreateDialMarkerValues();
                result = dial.actualDialMarkerValues;
                displayResult = dial.displayDialMarkerValues;
            });

            Assert.IsNotNull(result);
            Assert.IsNotNull(displayResult);
            Assert.AreEqual(3, result.Count);
            Assert.AreEqual(3, displayResult.Count);
            Assert.AreEqual(30, result[0]);
            Assert.AreEqual(50, result[1]);
            Assert.AreEqual(70, result[2]);
            Assert.AreEqual(30, displayResult[0]);
            Assert.AreEqual(50, displayResult[1]);
            Assert.AreEqual(70, displayResult[2]);
        }

        [TestMethod]
        public async Task CreateDialMarkerValues_lessThanThree()
        {
            List<double> result = null;
            ObservableCollection<double> displayResult = null;
            await TestUtil.GetDispatcher().RunAsync(CoreDispatcherPriority.Normal, () =>
            {
                var dial = new LinearDial
                {
                    Minimum = 30,
                    Maximum = 70,
                    MarkerInterval = 40
                };
                dial.CreateDialMarkerValues();
                result = dial.actualDialMarkerValues;
                displayResult = dial.displayDialMarkerValues;
            });

            Assert.IsNotNull(result);
            Assert.IsNotNull(displayResult);
            Assert.AreEqual(result.Count, 2);
            Assert.AreEqual(displayResult.Count, 2);
            Assert.AreEqual(30, result[0]);
            Assert.AreEqual(70, result[1]);
            Assert.AreEqual(30, displayResult[0]);
            Assert.AreEqual(70, displayResult[1]);
        }

        [TestMethod]
        public async Task CreateDialMarkerValues_moreThanThreeLooping()
        {
            List<double> result = null;
            ObservableCollection<double> displayResult = null;
            await TestUtil.GetDispatcher().RunAsync(CoreDispatcherPriority.Normal, () =>
            {
                var dial = new LinearDial
                {
                    IsLoopingEnabled = true,
                    Minimum = 30,
                    Maximum = 70,
                    MarkerInterval = 10
                };
                dial.CreateDialMarkerValues();
                result = dial.actualDialMarkerValues;
                displayResult = dial.displayDialMarkerValues;
            });

            Assert.IsNotNull(result);
            Assert.IsNotNull(displayResult);
            Assert.AreEqual(result.Count, 5);
            Assert.AreEqual(displayResult.Count, 5);
            Assert.AreEqual(30, result[0]);
            Assert.AreEqual(40, result[1]);
            Assert.AreEqual(50, result[2]);
            Assert.AreEqual(60, result[3]);
            Assert.AreEqual(30, result[4]);
            Assert.AreEqual(30, displayResult[0]);
            Assert.AreEqual(40, displayResult[1]);
            Assert.AreEqual(50, displayResult[2]);
            Assert.AreEqual(60, displayResult[3]);
            Assert.AreEqual(30, displayResult[4]);
        }

        [TestMethod]
        public async Task CreateDialMarkerValues_exactlyThreeLooping()
        {
            List<double> result = null;
            ObservableCollection<double> displayResult = null;
            await TestUtil.GetDispatcher().RunAsync(CoreDispatcherPriority.Normal, () =>
            {
                var dial = new LinearDial
                {
                    IsLoopingEnabled = true,
                    Minimum = 30,
                    Maximum = 70,
                    MarkerInterval = 20
                };
                dial.CreateDialMarkerValues();
                result = dial.actualDialMarkerValues;
                displayResult = dial.displayDialMarkerValues;
            });

            Assert.IsNotNull(result);
            Assert.IsNotNull(displayResult);
            Assert.AreEqual(3, result.Count);
            Assert.AreEqual(3, displayResult.Count);
            Assert.AreEqual(30, result[0]);
            Assert.AreEqual(50, result[1]);
            Assert.AreEqual(30, result[2]);
            Assert.AreEqual(30, displayResult[0]);
            Assert.AreEqual(50, displayResult[1]);
            Assert.AreEqual(30, displayResult[2]);
        }

        [TestMethod]
        public async Task CreateDialMarkerValues_lessThanThreeLooping()
        {
            List<double> result = null;
            ObservableCollection<double> displayResult = null;
            await TestUtil.GetDispatcher().RunAsync(CoreDispatcherPriority.Normal, () =>
            {
                var dial = new LinearDial
                {
                    IsLoopingEnabled = true,
                    Minimum = 30,
                    Maximum = 70,
                    MarkerInterval = 40
                };
                dial.CreateDialMarkerValues();
                result = dial.actualDialMarkerValues;
                displayResult = dial.displayDialMarkerValues;
            });

            Assert.IsNotNull(result);
            Assert.IsNotNull(displayResult);
            Assert.AreEqual(result.Count, 2);
            Assert.AreEqual(displayResult.Count, 2);
            Assert.AreEqual(30, result[0]);
            Assert.AreEqual(70, result[1]);
            Assert.AreEqual(30, displayResult[0]);
            Assert.AreEqual(70, displayResult[1]);
        }

        [TestMethod]
        public async Task NormalizeValue_BelowMin()
        {
            double minimum = 10;
            double maximum = 20;
            double result = 0;
            await TestUtil.GetDispatcher().RunAsync(CoreDispatcherPriority.Normal, () =>
            {
                var dial = new LinearDial
                {
                    Minimum = minimum,
                    Maximum = maximum
                };
                result = dial.NormalizeValue(minimum - 1);
            });

            Assert.AreEqual(minimum, result);
        }

        [TestMethod]
        public async Task NormalizeValue_AtMin()
        {
            double minimum = 10;
            double maximum = 20;
            double result = 0;
            await TestUtil.GetDispatcher().RunAsync(CoreDispatcherPriority.Normal, () =>
            {
                var dial = new LinearDial
                {
                    Minimum = minimum,
                    Maximum = maximum
                };
                result = dial.NormalizeValue(minimum);
            });

            Assert.AreEqual(minimum, result);
        }

        [TestMethod]
        public async Task NormalizeValue_WithinRange()
        {
            double minimum = 10;
            double maximum = 20;
            double result = 0;
            await TestUtil.GetDispatcher().RunAsync(CoreDispatcherPriority.Normal, () =>
            {
                var dial = new LinearDial
                {
                    Minimum = minimum,
                    Maximum = maximum
                };
                result = dial.NormalizeValue(minimum + 1);
            });

            Assert.AreEqual(minimum + 1, result);
        }

        [TestMethod]
        public async Task NormalizeValue_AtMax()
        {
            double minimum = 10;
            double maximum = 20;
            double result = 0;
            await TestUtil.GetDispatcher().RunAsync(CoreDispatcherPriority.Normal, () =>
            {
                var dial = new LinearDial
                {
                    Minimum = minimum,
                    Maximum = maximum
                };
                result = dial.NormalizeValue(maximum);
            });

            Assert.AreEqual(maximum, result);
        }

        [TestMethod]
        public async Task NormalizeValue_AboveMax()
        {
            double minimum = 10;
            double maximum = 20;
            double result = 0;
            await TestUtil.GetDispatcher().RunAsync(CoreDispatcherPriority.Normal, () =>
            {
                var dial = new LinearDial
                {
                    Minimum = minimum,
                    Maximum = maximum
                };
                result = dial.NormalizeValue(maximum + 1);
            });

            Assert.AreEqual(maximum, result);
        }

        [TestMethod]
        public async Task NormalizeValue_BelowMinLooping()
        {
            double minimum = 10;
            double maximum = 20;
            double result = 0;
            await TestUtil.GetDispatcher().RunAsync(CoreDispatcherPriority.Normal, () =>
            {
                var dial = new LinearDial
                {
                    IsLoopingEnabled = true,
                    Minimum = minimum,
                    Maximum = maximum
                };
                result = dial.NormalizeValue(minimum - 1);
            });

            Assert.AreEqual(maximum - 1, result);
        }

        [TestMethod]
        public async Task NormalizeValue_AtMinLooping()
        {
            double minimum = 10;
            double maximum = 20;
            double result = 0;
            await TestUtil.GetDispatcher().RunAsync(CoreDispatcherPriority.Normal, () =>
            {
                var dial = new LinearDial
                {
                    IsLoopingEnabled = true,
                    Minimum = minimum,
                    Maximum = maximum
                };
                result = dial.NormalizeValue(minimum);
            });

            Assert.AreEqual(minimum, result);
        }

        [TestMethod]
        public async Task NormalizeValue_WithinRangeLooping()
        {
            double minimum = 10;
            double maximum = 20;
            double result = 0;
            await TestUtil.GetDispatcher().RunAsync(CoreDispatcherPriority.Normal, () =>
            {
                var dial = new LinearDial
                {
                    IsLoopingEnabled = true,
                    Minimum = minimum,
                    Maximum = maximum
                };
                result = dial.NormalizeValue(minimum + 1);
            });

            Assert.AreEqual(minimum + 1, result);
        }

        [TestMethod]
        public async Task NormalizeValue_AtMaxLooping()
        {
            double minimum = 10;
            double maximum = 20;
            double result = 0;
            await TestUtil.GetDispatcher().RunAsync(CoreDispatcherPriority.Normal, () =>
            {
                var dial = new LinearDial
                {
                    IsLoopingEnabled = true,
                    Minimum = minimum,
                    Maximum = maximum
                };
                result = dial.NormalizeValue(maximum);
            });

            Assert.AreEqual(minimum, result);
        }

        [TestMethod]
        public async Task NormalizeValue_AboveMaxLooping()
        {
            double minimum = 10;
            double maximum = 20;
            double result = 0;
            await TestUtil.GetDispatcher().RunAsync(CoreDispatcherPriority.Normal, () =>
            {
                var dial = new LinearDial
                {
                    IsLoopingEnabled = true,
                    Minimum = minimum,
                    Maximum = maximum
                };
                result = dial.NormalizeValue(maximum + 1);
            });

            Assert.AreEqual(minimum + 1, result);
        }

        [TestMethod]
        public async Task GetDialScrollOffset_Min()
        {
            double minimum = 10;
            double maximum = 20;
            double markerSpacing = 57.5;
            double markerRange = 2.5;
            double result = -1;
            await TestUtil.GetDispatcher().RunAsync(CoreDispatcherPriority.Normal, () =>
            {
                var dial = new LinearDial
                {
                    Minimum = minimum,
                    Maximum = maximum,
                    markerSpacing = markerSpacing,
                    dialMarkerRange = markerRange
                };
                result = dial.GetDialScrollOffset(minimum);
            });

            Assert.AreEqual(0, result);
        }

        [TestMethod]
        public async Task GetDialScrollOffset_Max()
        {
            double minimum = 10;
            double maximum = 20;
            double markerSpacing = 57.5;
            double markerRange = 2.5;
            double result = -1;
            await TestUtil.GetDispatcher().RunAsync(CoreDispatcherPriority.Normal, () =>
            {
                var dial = new LinearDial
                {
                    Minimum = minimum,
                    Maximum = maximum,
                    markerSpacing = markerSpacing,
                    dialMarkerRange = markerRange
                };
                result = dial.GetDialScrollOffset(maximum);
            });

            Assert.AreEqual(markerSpacing * markerRange, result);
        }

        [TestMethod]
        public async Task GetDialScrollOffset_MinLooping()
        {
            double minimum = 10;
            double maximum = 20;
            double markerSpacing = 57.5;
            double markerRange = 2.5;
            double result = -1;
            await TestUtil.GetDispatcher().RunAsync(CoreDispatcherPriority.Normal, () =>
            {
                var dial = new LinearDial
                {
                    IsLoopingEnabled = true,
                    Minimum = minimum,
                    Maximum = maximum,
                    markerSpacing = markerSpacing,
                    dialMarkerRange = markerRange
                };
                result = dial.GetDialScrollOffset(minimum);
            });

            Assert.AreEqual(markerSpacing, result);
        }

        [TestMethod]
        public async Task GetDialScrollOffset_MaxLooping()
        {
            double minimum = 10;
            double maximum = 20;
            double markerSpacing = 57.5;
            double markerRange = 2.5;
            double result = -1;
            await TestUtil.GetDispatcher().RunAsync(CoreDispatcherPriority.Normal, () =>
            {
                var dial = new LinearDial
                {
                    IsLoopingEnabled = true,
                    Minimum = minimum,
                    Maximum = maximum,
                    markerSpacing = markerSpacing,
                    dialMarkerRange = markerRange
                };
                result = dial.GetDialScrollOffset(maximum);
            });

            Assert.AreEqual(markerSpacing * markerRange + markerSpacing, result);
        }

        [TestMethod]
        public async Task GetLoopingDialMarkers_NoWrap()
        {
            List<double> leftResults = null;
            List<double> rightResults = null;
            await TestUtil.GetDispatcher().RunAsync(CoreDispatcherPriority.Normal, () =>
            {
                var dial = new LinearDial();
                leftResults = dial.GetLeftLoopingDialValues(3, markerValueList);
                rightResults = dial.GetRightLoopingDialValues(3, markerValueList);
            });

            Assert.IsNotNull(leftResults);
            Assert.IsNotNull(rightResults);
            Assert.AreEqual(3, leftResults.Count);
            Assert.AreEqual(3, rightResults.Count);
            Assert.AreEqual(leftResults[0], 30);
            Assert.AreEqual(leftResults[1], 20);
            Assert.AreEqual(leftResults[2], 10);
            Assert.AreEqual(rightResults[0], 10);
            Assert.AreEqual(rightResults[1], 20);
            Assert.AreEqual(rightResults[2], 30);
        }

        [TestMethod]
        public async Task GetLoopingDialMarkers_Wrap()
        {
            List<double> leftResults = null;
            List<double> rightResults = null;
            await TestUtil.GetDispatcher().RunAsync(CoreDispatcherPriority.Normal, () =>
            {
                var dial = new LinearDial();
                leftResults = dial.GetLeftLoopingDialValues(7, markerValueList);
                rightResults = dial.GetRightLoopingDialValues(7, markerValueList);
            });

            Assert.IsNotNull(leftResults);
            Assert.IsNotNull(rightResults);
            Assert.AreEqual(7, leftResults.Count);
            Assert.AreEqual(7, rightResults.Count);
            Assert.AreEqual(leftResults[0], 30);
            Assert.AreEqual(leftResults[1], 20);
            Assert.AreEqual(leftResults[2], 10);
            Assert.AreEqual(leftResults[3], 0);
            Assert.AreEqual(leftResults[4], 30);
            Assert.AreEqual(leftResults[5], 20);
            Assert.AreEqual(leftResults[6], 10);
            Assert.AreEqual(rightResults[0], 10);
            Assert.AreEqual(rightResults[1], 20);
            Assert.AreEqual(rightResults[2], 30);
            Assert.AreEqual(rightResults[3], 0);
            Assert.AreEqual(rightResults[4], 10);
            Assert.AreEqual(rightResults[5], 20);
            Assert.AreEqual(rightResults[6], 30);
        }
    }


}
